﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BusinessModel;
using EntityDataModel;
using System.ComponentModel;
using Controller.DataProvider;
using System.Data;
using BaseUtilities;
using ManageStore.IViews;
using System.Collections.ObjectModel;

namespace Controller
{
    /// <summary>
    /// * Unnormal Properties : BuyOrderDetail
    /// </summary>
    public class BuyProductCtr : BaseCtr, IDataErrorInfo
    {
        public BuyProductCtr(IBuyProductView pIBuyProductView)
        {
            this.IBuyProductView = pIBuyProductView;
            ApplyDate = BuyDate = DateTime.Now;
        }

        CommandStatus _CommandStatus = CommandStatus.New;
        #region Properties
        // IBuyProductView.
        public IBuyProductView IBuyProductView { get; set; }
        // BuyOrderPro.
        private BuyOrderPro _BuyOrderPro;
        public BuyOrderPro BuyOrderPro
        {
            get
            {
                if (_BuyOrderPro == null)
                {
                    _BuyOrderPro = new BuyOrderPro();
                }
                return _BuyOrderPro;
            }
            set { _BuyOrderPro = value; }
        }
        // BuyOrderDetailPro.
        private BuyOrderDetailPro _BuyOrderDetailPro;
        public BuyOrderDetailPro BuyOrderDetailPro
        {
            get
            {
                if (_BuyOrderDetailPro == null)
                {
                    _BuyOrderDetailPro = new BuyOrderDetailPro();
                }
                return _BuyOrderDetailPro;
            }
            set { _BuyOrderDetailPro = value; }
        }
        // ProductPro.
        private ProductPro _ProductPro;
        public ProductPro ProductPro
        {
            get
            {
                if (_ProductPro == null)
                {
                    _ProductPro = new ProductPro();
                }
                return _ProductPro;
            }
            set { _ProductPro = value; }
        }
        // UnitChangePro.
        private UnitChangePro _UnitChangePro;
        public UnitChangePro UnitChangePro
        {
            get
            {
                if (_UnitChangePro == null)
                {
                    _UnitChangePro = new UnitChangePro();
                }
                return _UnitChangePro;
            }
            set { _UnitChangePro = value; }
        }
        // ProductTypePro.
        private ProductTypePro _ProductTypePro;
        public ProductTypePro ProductTypePro
        {
            get
            {
                if (_ProductTypePro == null)
                {
                    _ProductTypePro = new ProductTypePro();
                }
                return _ProductTypePro;
            }
            set { _ProductTypePro = value; }
        }

        // LstErrorFields
        private Dictionary<string, string> _DicError;
        public Dictionary<string, string> DicError
        {
            get
            {
                if (_DicError == null)
                    _DicError = new Dictionary<string, string>();
                return _DicError;
            }
            set
            {
                _DicError = value;
            }
        }
        // PropertyChangedName
        public string PropertyChangedName { get; set; }
        #endregion Properties

        #region Binding properties
        // Id
        public int Id
        {
            get
            {
                return BuyOrderDetail.Id;
            }
            set
            {
                if (BuyOrderDetail.Id != value)
                {
                    BuyOrderDetail.Id = value;
                    OnPropertyChanged("Id");
                }
            }
        }
        // ProductId
        private int? _ProductId;
        public int? ProductId
        {
            get
            {
                return _ProductId;
            }
            set
            {
                _ProductId = value;
                OnPropertyChanged("ProductId");
                IList<UnitChange> lstUnitChange = null;
                if (value.HasValue)
                {
                    BuyOrderDetail.ProductId = value;
                    Product.Id = value.Value;
                    Product oProduct = LstProduct.Where(p => p.Id == value.Value).FirstOrDefault();
                    if (oProduct != null)
                    {
                        //Product.Quantity = oProduct.Quantity; Not true. Because Quantity alway update.
                        UnitId = oProduct.UnitId;
                        UnitName = oProduct.UnitName;
                    }
                    if (Product.UnitChanges == null || Product.UnitChanges.Count == 0)
                    {
                        lstUnitChange = GetUnitChangeByProductId(value.Value).ToResult<List<UnitChange>>()
                                 .Where(p => !p.ApplyDate.HasValue || p.ApplyDate.Value.Date <= DateTime.Now.Date)
                                 .OrderByDescending(p => p.ApplyDate).ToList();
                        IList<UnitChange> lstResult = new List<UnitChange>();
                        foreach (UnitChange item in lstUnitChange)
                        {
                            if (lstResult.Where(p => p.Level == item.Level).FirstOrDefault() == null)
                                lstResult.Add(item);
                        }
                        lstUnitChange = lstResult;
                    }
                    else
                    {
                        lstUnitChange = Product.UnitChanges;
                    }
                }
                else
                {
                    UnitId = null;
                    UnitName = string.Empty;
                }
                if(lstUnitChange == null || lstUnitChange.Count == 0)
                {
                    lstUnitChange = MtdCreateUnitChanges();
                    ApplyDate = BuyDate = DateTime.Now;
                }
                MtdSetUnitChanges(lstUnitChange, value);
            }
        }

        private IList<UnitChange> MtdCreateUnitChanges()
        {
            IList<UnitChange> result = new List<UnitChange>();
            UnitChange oUnitChange;
            // For 4 Unit Level with 0 = Root.
            for (int i = 0; i < 4; i++)
            {
                oUnitChange = new UnitChange();
                oUnitChange.Level = i;
                //oUnitChange.Quantity = 1;
                result.Add(oUnitChange);
            }
            // UnitWholeSale.
            oUnitChange = new UnitChange();
            //oUnitChange.Quantity = 1;
            result.Add(oUnitChange);
            return result;
        }

        private void MtdSetUnitChanges(IList<UnitChange> pUnitChanges, int? pProductId)
        {
            //pUnitChanges.ToList().ForEach((item) =>
            foreach (UnitChange item in pUnitChanges)
            {
                switch (item.Level)
                {
                    case 0:
                        item.Quantity = 1;
                        UnitChangeLevel0.ProductId = pProductId;
                        UnitChangeLevel0.UnitId = BuyOrderDetail.UnitId;
                        UnitChangeLevel0.Quantity = item.Quantity;
                        //UnitChangeLevel0.SalePriceUnit = item.SalePriceUnit;
                        ApplyDate = item.ApplyDate;
                        SalePriceUnit = item.SalePriceUnit;
                        break;
                    case 1:
                        UnitChangeLevel1.ProductId = pProductId;
                        UnitChangeLevel1.UnitId = item.UnitId;
                        UnitChangeLevel1.Quantity = item.Quantity;
                        UnitChangeLevel1.SalePriceUnit = item.SalePriceUnit;
                        OnPropertyChanged("UnitChangeLevel1");
                        break;
                    case 2:
                        UnitChangeLevel2.ProductId = pProductId;
                        UnitChangeLevel2.UnitId = item.UnitId;
                        UnitChangeLevel2.Quantity = item.Quantity;
                        UnitChangeLevel2.SalePriceUnit = item.SalePriceUnit;
                        break;
                    case 3:
                        UnitChangeLevel3.ProductId = pProductId;
                        UnitChangeLevel3.UnitId = item.UnitId;
                        UnitChangeLevel3.Quantity = item.Quantity;
                        UnitChangeLevel3.SalePriceUnit = item.SalePriceUnit;
                        break;
                    default:
                        UnitChangeWholeSale.ProductId = pProductId;
                        UnitChangeWholeSale.UnitId = item.UnitId;
                        UnitChangeWholeSale.Quantity = item.Quantity;
                        UnitChangeWholeSale.SalePriceUnit = item.SalePriceUnit;
                        break;
                }
            };
        }

        private IList<UnitChange> MtdGetUnitChanges()
        {
            IList<UnitChange> result = new List<UnitChange>();
            result.Add(UnitChangeLevel0);
            result.Add(UnitChangeLevel1);
            result.Add(UnitChangeLevel2);
            result.Add(UnitChangeLevel3);
            result.Add(UnitChangeWholeSale);
            return result;
        }

        // ProductTypeId
        public int ProductTypeId
        {
            get
            {
                return BuyOrderDetail.Product.TypeId;
            }
            set
            {
                if (BuyOrderDetail.Product.TypeId != value)
                {
                    BuyOrderDetail.Product.TypeId = value;
                    //OnPropertyChanged("ProductTypeId");
                }
            }
        }
        // SupplierId
        public int? SupplierId
        {
            get
            {
                return BuyOrderDetail.SupplierId;
            }
            set
            {
                if (BuyOrderDetail.SupplierId != value)
                {
                    BuyOrderDetail.SupplierId = value;
                    //OnPropertyChanged("SupplierId");
                }
            }
        }
        // ProductTypeName
        public string ProductTypeName
        {
            get
            {
                return BuyOrderDetail.Product.Name;
            }
            set
            {
                if (BuyOrderDetail.Product.Name != value)
                {
                    BuyOrderDetail.Product.Name = value;
                    //OnPropertyChanged("ProductTypeName");
                }
            }
        }
        // ProductCode
        public string ProductCode
        {
            get
            {
                return BuyOrderDetail.Code;
            }
            set
            {
                if (BuyOrderDetail.Code != value)
                {
                    BuyOrderDetail.Code = value;
                    //OnPropertyChanged("ProductCode");
                }
            }
        }
        // ProductName
        public string ProductName
        {
            get
            {
                return BuyOrderDetail.Name;
            }
            set
            {
                if (BuyOrderDetail.Name != value)
                {
                    BuyOrderDetail.Name = value;
                    //OnPropertyChanged("ProductName");
                }
            }
        }
        // ProductName
        int iGetCount, iSetCount;
        public int? Quantity
        {
            get
            {
                iGetCount++;
                return BuyOrderDetail.Quantity;
            }
            set
            {
                iSetCount++;
                if (BuyOrderDetail.Quantity != value)
                {
                    BuyOrderDetail.Quantity = value;
                    //OnPropertyChanged("Quantity");
                }
            }
        }
        // UnitId.
        public int? UnitId
        {
            get
            {
                return BuyOrderDetail.UnitId;
            }
            set
            {
                if (BuyOrderDetail.UnitId != value)
                {
                    BuyOrderDetail.UnitId = value;
                    UnitChangeLevel0.UnitId = value;
                    UnitChangeWholeSale.UnitId = value;
                    //OnPropertyChanged("UnitId");
                }
            }
        }
        // UnitName
        public string UnitName
        {
            get
            {
                return BuyOrderDetail.UnitName;
            }
            set
            {
                if (BuyOrderDetail.UnitName != value)
                {
                    BuyOrderDetail.UnitName = value;
                    UnitChangeLevel0.UnitName = value;
                    OnPropertyChanged("UnitName");
                }
            }
        }
        // BuyPriceUnit
        public int? BuyPriceUnit
        {
            get
            {
                return BuyOrderDetail.BuyPriceUnit;
            }
            set
            {
                if (BuyOrderDetail.BuyPriceUnit != value)
                {
                    BuyOrderDetail.BuyPriceUnit = value;
                    //OnPropertyChanged("BuyPriceUnit");
                }
            }
        }
        // SalePriceUnit
        public int? SalePriceUnit
        {
            get
            {
                return BuyOrderDetail.SalePriceUnit;
            }
            set
            {
                if (BuyOrderDetail.SalePriceUnit != value)
                {
                    BuyOrderDetail.SalePriceUnit = value;
                    UnitChangeLevel0.SalePriceUnit = value;
                    //OnPropertyChanged("SalePriceUnit");
                }
            }
        }
        // DiscountTypeId
        public int? DiscountTypeId
        {
            get
            {
                return BuyOrderDetail.DiscountTypeId;
            }
            set
            {
                if (BuyOrderDetail.DiscountTypeId != value)
                {
                    BuyOrderDetail.DiscountTypeId = value;
                    //OnPropertyChanged("DiscountTypeId");
                }
            }
        }
        // DiscountValue
        public int? DiscountValue
        {
            get
            {
                return BuyOrderDetail.DiscountValue;
            }
            set
            {
                if (BuyOrderDetail.DiscountValue != value)
                {
                    BuyOrderDetail.DiscountValue = value;
                    //OnPropertyChanged("DiscountValues");
                }
            }
        }
        // IsConsign
        public bool IsConsign
        {
            get
            {
                if (!BuyOrderDetail.IsConsign.HasValue)
                    BuyOrderDetail.IsConsign = false;
                return BuyOrderDetail.IsConsign.Value;
            }
            set
            {
                if (BuyOrderDetail.IsConsign != value)
                {
                    BuyOrderDetail.IsConsign = value;
                    //OnPropertyChanged("IsConsign");
                }
            }
        }
        // BuyDate
        public DateTime? BuyDate
        {
            get
            {
                return BuyOrderDetail.BuyDate;
            }
            set
            {
                if (BuyOrderDetail.BuyDate != value)
                {
                    BuyOrderDetail.BuyDate = value;
                    //OnPropertyChanged("BuyDate");
                }
            }
        }
        // ApplyDate
        private DateTime? _ApplyDate;
        public DateTime? ApplyDate
        {
            get
            {
                if (_ApplyDate == null)
                    _ApplyDate = DateTime.Now;
                return _ApplyDate;
            }
            set
            {
                if (_ApplyDate != value)
                {
                    _ApplyDate = value;
                    OnPropertyChanged("ApplyDate");
                }
            }
        }
        // ProductNote
        public string ProductNote
        {
            get
            {
                return BuyOrderDetail.Note;
            }
            set
            {
                if (BuyOrderDetail.Note != value)
                {
                    BuyOrderDetail.Note = value;
                    //OnPropertyChanged("ProductNote");
                }
            }
        }
        // Total
        private int _Total;
        public int Total
        {
            get
            {
                return _Total;
            }
            set
            {
                if (_Total != value)
                {
                    _Total = value;
                    OnPropertyChanged("Total");
                }
            }
        }

        // BuyOrder.
        private BuyOrder _BuyOrder;
        public BuyOrder BuyOrder
        {
            get
            {
                if (_BuyOrder == null)
                {
                    _BuyOrder = new BuyOrder();
                    _BuyOrder.BuyOrderDetails = LstBuyOrderDetail;
                    //OnPropertyChanged("LstBuyOrderDetail");
                }
                return _BuyOrder;
            }
            set { _BuyOrder = value; OnPropertyChanged("BuyOrder"); }
        }
        // BuyOrderDetail.
        private BuyOrderDetail _BuyOrderDetail;
        public BuyOrderDetail BuyOrderDetail
        {
            get
            {
                if (_BuyOrderDetail == null)
                {
                    _BuyOrderDetail = new BuyOrderDetail();
                    _BuyOrderDetail.Product = Product;
                    //OnPropertyChanged("Product");
                }
                return _BuyOrderDetail;
            }
            set 
            {
                if (_BuyOrderDetail != value)
                {
                    _BuyOrderDetail = value;
                    //OnPropertyChanged("BuyOrderDetail");
                }
            }
        }
        // Product.
        //private Product _Product;
        public Product Product
        {
            get
            {
                if (BuyOrderDetail.Product == null)
                {
                    BuyOrderDetail.Product = new Product();
                    BuyOrderDetail.Product.ApplyDate = DateTime.Now;
                    //BuyOrderDetail.Product.UnitChanges = UnitChanges;
                    //OnPropertyChanged("UnitChanges");
                }
                return BuyOrderDetail.Product;
            }
            set { BuyOrderDetail.Product = value; OnPropertyChanged("Product"); }
        }
        // UnitChangeLevel0.
        private UnitChange _UnitChangeLevel0;
        public UnitChange UnitChangeLevel0
        {
            get
            {
                if (_UnitChangeLevel0 == null)
                {
                    _UnitChangeLevel0 = new UnitChange();
                    _UnitChangeLevel0.Level = 0;
                    _UnitChangeLevel0.Quantity = 1;
                }
                return _UnitChangeLevel0;
            }
            set
            {
                _UnitChangeLevel0 = value; 
                //OnPropertyChanged("UnitChangeLevel0");
            }
        }
        // UnitChangeLevel1.
        private UnitChange _UnitChangeLevel1;
        public UnitChange UnitChangeLevel1
        {
            get
            {
                if (_UnitChangeLevel1 == null)
                {
                    _UnitChangeLevel1 = new UnitChange();
                    _UnitChangeLevel1.Level = 1;
                }
                return _UnitChangeLevel1;
            }
            set
            {
                _UnitChangeLevel1 = value;
                //OnPropertyChanged("UnitChangeLevel1"); 
            }
        }
        // UnitChangeLevel2.
        private UnitChange _UnitChangeLevel2;
        public UnitChange UnitChangeLevel2
        {
            get
            {
                if (_UnitChangeLevel2 == null)
                {
                    _UnitChangeLevel2 = new UnitChange();
                    _UnitChangeLevel2.Level = 2;
                }
                return _UnitChangeLevel2;
            }
            set
            {
                _UnitChangeLevel2 = value;
                //OnPropertyChanged("UnitChangeLevel2");
            }
        }
        // UnitChangeLevel3.
        private UnitChange _UnitChangeLevel3;
        public UnitChange UnitChangeLevel3
        {
            get
            {
                if (_UnitChangeLevel3 == null)
                {
                    _UnitChangeLevel3 = new UnitChange();
                    _UnitChangeLevel3.Level = 3;
                }
                return _UnitChangeLevel3;
            }
            set
            {
                _UnitChangeLevel3 = value;
                //OnPropertyChanged("UnitChangeLevel3");
            }
        }
        // UnitChangeWholeSale.
        private UnitChange _UnitChangeWholeSale;
        public UnitChange UnitChangeWholeSale
        {
            get
            {
                if (_UnitChangeWholeSale == null)
                {
                    _UnitChangeWholeSale = new UnitChange();
                }
                return _UnitChangeWholeSale;
            }
            set
            {
                _UnitChangeWholeSale = value;
                //OnPropertyChanged("UnitChangeWholeSale");
            }
        }
        // LstBuyOrderDetail.
        private IList<BuyOrderDetail> _LstBuyOrderDetail;
        public IList<BuyOrderDetail> LstBuyOrderDetail
        {
            get
            {
                if (_LstBuyOrderDetail == null)
                {
                    _LstBuyOrderDetail = new ObservableCollection<BuyOrderDetail>();
                }
                return _LstBuyOrderDetail;
            }
            set
            {
                if (_LstBuyOrderDetail != value)
                {
                    _LstBuyOrderDetail = value;
                    OnPropertyChanged("LstBuyOrderDetail");
                }
            }
        }
        // LstProduct.
        private IList<Product> _LstProduct;
        public IList<Product> LstProduct
        {
            get
            {
                if (_LstProduct == null)
                {
                    _LstProduct = GetAllProduct().ToResult<IList<Product>>();
                }
                return _LstProduct;
            }
            set
            {
                if (_LstProduct != value)
                {
                    _LstProduct = value;
                    OnPropertyChanged("LstProduct");
                }
            }
        }
        // LstProductType.
        private IList<ProductType> _LstProductType;
        public IList<ProductType> LstProductType
        {
            get
            {
                if (_LstProductType == null)
                {
                    _LstProductType = new ObservableCollection<ProductType>(GetroductTypeAllLeafs().ToResult<IList<ProductType>>());
                }
                return _LstProductType;
            }
            set
            {
                if (_LstProductType != value)
                {
                    _LstProductType = value;
                    OnPropertyChanged("LstProductType");
                }
            }
        }
        // LstSupplier.
        private IList<IdNameModel> _LstSupplier;
        public IList<IdNameModel> LstSupplier
        {
            get
            {
                if (_LstSupplier == null)
                {
                    _LstSupplier = new ObservableCollection<IdNameModel>(GetSupplierAll().ToResult<IList<IdNameModel>>());
                }
                return _LstSupplier;
            }
            set
            {
                if (_LstSupplier != value)
                {
                    _LstSupplier = value;
                    OnPropertyChanged("LstSupplier");
                }
            }
        }
        // LstDiscountType.
        private IList<IdNameModel> _LstDiscountType;
        public IList<IdNameModel> LstDiscountType
        {
            get
            {
                if (_LstDiscountType == null)
                {
                    _LstDiscountType = new ObservableCollection<IdNameModel>(GetDiscountTypeAll().ToResult<IList<IdNameModel>>());
                }
                return _LstDiscountType;
            }
            set
            {
                if (_LstDiscountType != value)
                {
                    _LstDiscountType = value;
                    OnPropertyChanged("LstDiscountType");
                }
            }
        }
        // LstUnit.
        private IList<IdNameModel> _LstUnit;
        public IList<IdNameModel> LstUnit
        {
            get
            {
                if (_LstUnit == null)
                {
                    _LstUnit = new ObservableCollection<IdNameModel>(GetUnitAll().ToResult<IList<IdNameModel>>());
                }
                return _LstUnit.Select(p => p).ToList();
            }
            set
            {
                if (_LstUnit != value)
                {
                    _LstUnit = value;
                    //OnPropertyChanged("LstUnit");
                }
            }
        }
        #endregion Binding properties

        #region Private Method
        //----------------------------------------
        private void LoadListBuyOrderDetail()
        {
            LstBuyOrderDetail = new ObservableCollection<BusinessModel.BuyOrderDetail>(MtdGetAll().ToResult<IList<BuyOrderDetail>>());
        }
        //----------------------------------------
        private ResultModel MtdGetById(int pBuyOrderDetailId)
        {
            EntityKey oEntityKey = new EntityKey(BaseProvider.QualifyName + "." + BuyOrderDetailPro.EntityName, "Id", pBuyOrderDetailId);
            return BuyOrderDetailPro.GetById(oEntityKey);
        }
        //----------------------------------------
        private ResultModel MtdGetAll()
        {
            return BuyOrderDetailPro.GetAll();
        }
        //----------------------------------------
        private int MtdCountTotal()
        {
            int result = 0;
            foreach (BuyOrderDetail item in LstBuyOrderDetail)
            {
                if (item.Total.HasValue)
                    result += item.Total.Value;
            }
            return result;
        }
        #endregion Private Method

        #region Public View Handlers
        //----------------------------------------
        public bool MtdNew(params object[] pParams)
        {
            bool result = false;
            if (IBuyProductView.BeforeHandler("EvtNew"))
            {
                DicError.Clear();
                
                BuyOrderDetail = null;
                ProductId = null;
                IBuyProductView.CompletedHandler("EvtNew");
            }
            return result;
        }
        //----------------------------------------
        public bool MtdEdit(params object[] pParams)
        {
            bool result = false;
            if (IBuyProductView.BeforeHandler("EvtEdit"))
            {
                if (pParams.Count() == 1)
                {
                    BuyOrderDetail oBuyOrderDetail = pParams[0] as BuyOrderDetail;
                    if (oBuyOrderDetail == null)
                    {
                        IBuyProductView.ErrorHandler("EvtEdit");
                    }
                    else
                    {
                        BuyOrderDetail = LstBuyOrderDetail.Where(p => p.ProductId == oBuyOrderDetail.ProductId).FirstOrDefault();
                        ProductId = BuyOrderDetail.ProductId;
                        DicError.Clear();
                        IBuyProductView.CompletedHandler("EvtEdit");
                    }
                }
            }
            return result;
        }
        private IList<UnitChange> MtdCopyUnitChanges(IList<UnitChange> pUnitChanges)
        {
            IList<UnitChange> result = new List<UnitChange>();
            foreach (UnitChange item in Product.UnitChanges)
            {
                UnitChange oUnitChange = new UnitChange();
                oUnitChange.Level = item.Level;
                oUnitChange.UnitId = item.UnitId;
                oUnitChange.Quantity = item.Quantity;
                oUnitChange.SalePriceUnit = item.SalePriceUnit;
                result.Add(oUnitChange);
            }
            return result;
        }
        //----------------------------------------
        public bool MtdDelete(params object[] pParams)
        {
            bool result = false;
            if (IBuyProductView.BeforeHandler("EvtDelete"))
            {
                BuyOrder = new BuyOrder();
                LstBuyOrderDetail = BuyOrder.BuyOrderDetails;
                IBuyProductView.ReloadData();
                IBuyProductView.CompletedHandler("EvtDelete");
                result = true;
            }
            return result;
        }
        //----------------------------------------
        public bool MtdSave(params object[] pParams)
        {
            // Check validate.
            if (LstProduct.Count == 0)
            {
                IBuyProductView.ErrorHandler("EvtSave");
                return false;
            }
            bool result = false;
            if (IBuyProductView.BeforeHandler("EvtSave"))
            {
                foreach (BuyOrderDetail item in LstBuyOrderDetail)
                {
                    if (item.Id == default(int))
                    {
                        item.CreatedBy = ControllerConfig.Default.UserName;
                        item.CreatedDate = DateTime.Now;
                    }
                    item.ModifiedBy = ControllerConfig.Default.UserName;
                    item.ModifiedDate = DateTime.Now;
                }
                BuyOrder.BuyOrderDetails = LstBuyOrderDetail;
                //EntityKey oEntityKey = new EntityKey(BaseProvider.QualifyName + "." + BuyOrderDetailPro.EntityName, "Id", BuyOrderDetail.Id);
                //ResultModel oResultModel = BuyOrderDetailPro.Save(BuyOrderDetail, oEntityKey);
                ResultModel oResultModel = SaveBuyOrder(BuyOrder);
                if (oResultModel.HasError)
                {
                    IBuyProductView.ErrorHandler("EvtSave", oResultModel);
                }
                else
                {
                    BuyOrder = new BuyOrder();
                    this.Total = 0;
                    LstBuyOrderDetail = BuyOrder.BuyOrderDetails;
                    IBuyProductView.ReloadData();
                    IBuyProductView.CompletedHandler("EvtSave", oResultModel.Result);
                    result = true;
                }
            }
            return result;
        }
        //----------------------------------------
        public bool MtdGetAllChilds(Action<object> pAction, params object[] pParams)
        {
            bool result = false;
            int? iParentId = null;
            if (pParams.Count() == 1)
            {
                iParentId = int.Parse(pParams[0].ToString());
            }
            IList<ProductType> lstPro = ProductTypePro.GetAllChilds(iParentId).ToResult<IList<ProductType>>();
            pAction(lstPro);
            return result;
        }
        //----------------------------------------
        private void MtdCheckValidate()
        {
            string error = string.Empty;
            DicError.Clear();
            if (!BuyOrderDetail.ProductId.HasValue)
            {
                error = "Tên hàng hóa không được rỗng";
                DicError.Add("ProductName", error);
                IBuyProductView.ValidationHandler("ProductName", error);
            }
            // Quantity.
            if (!BuyOrderDetail.Quantity.HasValue)
            {
                error = "Số lượng không được rỗng";
                DicError.Add("Quantity", error);
                IBuyProductView.ValidationHandler("Quantity", error);
            }
            else
            {
                if (BuyOrderDetail.Quantity < 1)
                {
                    error = "Nhập vào số nguyên dương";
                    DicError.Add("Quantity", error);
                    IBuyProductView.ValidationHandler("Quantity", error);
                }
            }
            // BuyPriceUnit.
            if (!BuyOrderDetail.BuyPriceUnit.HasValue)
            {
                error = "Đơn giá mua không được rỗng";
                DicError.Add("BuyPriceUnit", error);
                IBuyProductView.ValidationHandler("BuyPriceUnit", error);
            }
            else
            {
                if (BuyOrderDetail.BuyPriceUnit < 1)
                {
                    error = "Nhập vào số nguyên dương";
                    DicError.Add("BuyPriceUnit", error);
                    IBuyProductView.ValidationHandler("BuyPriceUnit", error);
                }
            }
            // SalePriceUnit.
            if (!BuyOrderDetail.SalePriceUnit.HasValue)
            {
                error = "Đơn giá bán không được rỗng";
                DicError.Add("SalePriceUnit", error);
                IBuyProductView.ValidationHandler("SalePriceUnit", error);
            }
            else
            {
                if (BuyOrderDetail.SalePriceUnit < 1)
                {
                    error = "Nhập vào số nguyên dương";
                    DicError.Add("SalePriceUnit", error);
                    IBuyProductView.ValidationHandler("SalePriceUnit", error);
                }
            }
        }
        //----------------------------------------
        private bool CheckUniqueUnitChanges()
        {
            List<int> lstUnitId = new List<int>();
            if (UnitId.HasValue)
                lstUnitId.Add(UnitId.Value);
            if (UnitChangeLevel1.UnitId.HasValue)
            {
                if (lstUnitId.Contains(UnitChangeLevel1.UnitId.Value))
                    return true;
                else
                    lstUnitId.Add(UnitChangeLevel1.UnitId.Value);
            }
            if (UnitChangeLevel2.UnitId.HasValue)
            {
                if (lstUnitId.Contains(UnitChangeLevel2.UnitId.Value))
                    return true;
                else
                    lstUnitId.Add(UnitChangeLevel2.UnitId.Value);
            }
            if (UnitChangeLevel3.UnitId.HasValue)
            {
                if (lstUnitId.Contains(UnitChangeLevel3.UnitId.Value))
                    return true;
                else
                    lstUnitId.Add(UnitChangeLevel3.UnitId.Value);
            }
            return false;
        }
        public bool MtdAdd(params object[] pParams)
        {
            // Check validate.
            if (DicError.Count > 0)
            {
                IBuyProductView.ErrorHandler("EvtAdd", DicError);
                return false;
            }
            // Check unique UnitChanges.
            if(CheckUniqueUnitChanges())
            {
                IBuyProductView.ErrorHandler("EvtAdd", "Đơn vị tính không được trùng");
                return false;
            }
            bool result = false;
            if (IBuyProductView.BeforeHandler("EvtAdd"))
            {
                BuyOrderDetail oBuyOrderDetail = LstBuyOrderDetail.Where(p => p.ProductId == BuyOrderDetail.ProductId).FirstOrDefault();
                if (oBuyOrderDetail == null)
                {
                    LstBuyOrderDetail.Add(BuyOrderDetail);
                }
                else
                {
                    // New. Replace Old by New. Notify Message.
                    if (Product.UnitChanges == null || Product.UnitChanges.Count == 0)
                    {
                        LstBuyOrderDetail.Remove(oBuyOrderDetail);
                        LstBuyOrderDetail.Add(BuyOrderDetail);
                    }
                }
                BuyOrderDetail.Total = 0;
                if (BuyOrderDetail.Quantity.HasValue && BuyOrderDetail.BuyPriceUnit.HasValue)
                {
                    BuyOrderDetail.Total = BuyOrderDetail.Quantity.Value * BuyOrderDetail.BuyPriceUnit.Value;
                }
                Product.UnitChanges = MtdGetUnitChanges();
                IList<UnitChange> lstCh = new List<UnitChange>();
                foreach (UnitChange item in Product.UnitChanges)
                {
                    UnitChange oUnitChange = new UnitChange();
                    oUnitChange.Level = item.Level;
                    oUnitChange.UnitId = item.UnitId;
                    oUnitChange.Quantity = item.Quantity;
                    oUnitChange.SalePriceUnit = item.SalePriceUnit;
                    oUnitChange.ApplyDate = ApplyDate;
                    lstCh.Add(oUnitChange);
                }
                Product.ApplyDate = ApplyDate;
                Product.UnitChanges = lstCh;
                this.Total = MtdCountTotal();
                IBuyProductView.ReloadData();
                DicError.Clear();
                IBuyProductView.CompletedHandler("EvtAdd");
            }
            return result;
        }
        //----------------------------------------
        public bool MtdRemove(params object[] pParams)
        {
            if (BuyOrderDetail.Code == "")
            {
                IBuyProductView.BeforeHandler("EvtRemove", "NoItem");
                return true;
            }
            bool result = true;
            if (result = IBuyProductView.BeforeHandler("EvtRemove") && LstBuyOrderDetail.Remove(BuyOrderDetail))
            {
                //OnPropertyChanged("LstBuyOrderDetail");
                this.Total = MtdCountTotal();
                BuyOrderDetail = null;
                IBuyProductView.ReloadData();
                DicError.Clear();
                IBuyProductView.CompletedHandler("EvtRemove");
            }
            return result;
        }
        //----------------------------------------
        public bool MtdLoadProduct(params object[] pParams)
        {
            bool result = false;
            if (IBuyProductView.BeforeHandler("EvtLoadProduct"))
            {
                if (pParams.Count() == 1 && pParams[0] != null)
                {
                    int iProductTypeId = 0;
                    int.TryParse(pParams[0].ToString(), out iProductTypeId);
                    LstProduct = GetAllByTypeId(iProductTypeId).ToResult<IList<Product>>();
                }
                else
                {
                    LstProduct = GetAllProduct().ToResult<IList<Product>>();
                }
                IBuyProductView.CompletedHandler("EvtLoadProduct");
            }
            return result;
        }
        //----------------------------------------
        public bool MtdLoadSupplier(params object[] pParams)
        {
            bool result = false;
            if (IBuyProductView.BeforeHandler("EvtLoadSupplier"))
            {
                LstSupplier = null;
                IBuyProductView.CompletedHandler("EvtLoadSupplier");
            }
            return result;
        }
        #endregion Public View Handlers

        #region IDataErrorInfo Members
        private string _Error;
        public string Error
        {
            get
            {
                return _Error;
            }
        }
        public string this[string columnName]
        {
            get
            {
                string error = string.Empty;
                if (DicError.Keys.Contains(columnName))
                    DicError.Remove(columnName);
                switch (columnName)
                {
                    case "ProductName":
                        if (string.IsNullOrWhiteSpace(ProductName))
                        {
                            error = "Tên hàng hóa không được rỗng.";
                        }
                        break;
                    case "ProductId":
                        if (!ProductId.HasValue || ProductId.Value == default(int))
                        {
                            error = "Tên hàng hóa không được rỗng.";
                        }
                        break;
                    case "Quantity":
                        if (!Quantity.HasValue)
                        {
                            error = "Số lượng không được rỗng.";
                        }
                        break;
                    case "BuyPriceUnit":
                        if (!BuyPriceUnit.HasValue)
                        {
                            error = "Số lượng không được rỗng.";
                        }
                        break;
                    case "SalePriceUnit":
                        if (!SalePriceUnit.HasValue)
                        {
                            error = "Số lượng không được rỗng.";
                        }
                        break;
                }
                _Error = error;
                if(!string.IsNullOrWhiteSpace(error))
                {
                    DicError.Add(columnName, error);
                }
                IBuyProductView.ValidationHandler(columnName, error);
                return error;
            }
        }
        #endregion

        #region Public Methods
        //----------------------------------------
        public ResultModel Save(Product pProduct)
        {
            EntityKey oEntityKey = new EntityKey(BaseProvider.QualifyName + "." + ProductPro.EntityName, "Id", pProduct.Id);
            return ProductPro.Save(pProduct, oEntityKey);
        }
        //----------------------------------------
        public ResultModel DeleteById(int pId)
        {
            EntityKey oEntityKey = new EntityKey(BaseProvider.QualifyName + "." + ProductPro.EntityName, "Id", pId);
            return ProductPro.DeleteById(oEntityKey);
        }
        //----------------------------------------
        public ResultModel GetById(int pId)
        {
            EntityKey oEntityKey = new EntityKey(BaseProvider.QualifyName + "." + ProductPro.EntityName, "Id", pId);
            return ProductPro.GetById(oEntityKey);
        }
        //----------------------------------------
        public ResultModel GetAllProduct()
        {
            return ProductPro.GetAll();
        }
        //----------------------------------------
        public ResultModel GetAllByTypeId(int pTypeId)
        {
            return ProductPro.GetAllByTypeId(pTypeId);
        }
        // Extend Methods.
        //----------------------------------------
        public ResultModel GetTypeByProductId(int pProductId)
        {
            return ProductPro.GetTypeById(pProductId);
        }
        //----------------------------------------
        public ResultModel GetroductTypeAllLeafs()
        {
            return ProductTypePro.GetAllLeafs();
        }
        //----------------------------------------
        public ResultModel GetCodeAll()
        {
            return ProductPro.GetIdNameAll("Id", "Code");
        }
        //----------------------------------------
        public ResultModel GetIdNameAll()
        {
            return ProductPro.GetIdNameAll();
        }
        //----------------------------------------
        public ResultModel GetIdNameAllByTypeId(int pTypeId)
        {
            return ProductPro.GetIdNameAllByTypeId(pTypeId);
        }
        //----------------------------------------
        public ResultModel GetUnitAll()
        {
            return (new UnitPro()).GetIdNameAll();
        }
        //----------------------------------------
        public ResultModel GetSupplierAll()
        {
            return (new SupplierPro()).GetIdNameAll();
        }
        //----------------------------------------
        public ResultModel GetDiscountTypeAll()
        {
            return (new DiscountTypePro()).GetIdNameAll();
        }
        //----------------------------------------
        public ResultModel GetUnitChangeByProductId(int pProductId)
        {
            return this.UnitChangePro.GetsByProductId(pProductId);
        }
        #endregion Public Methods
        //----------------------------------------
        public ResultModel SaveBuyOrder(BuyOrder pBuyOrder)
        {
            EntityKey oEntityKey = new EntityKey(BaseProvider.QualifyName + "." + ProductPro.EntityName, "Id", pBuyOrder.Id);
            return BuyOrderPro.SaveBuyOrderFull(pBuyOrder);
        }
    }
}
